﻿using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using Daybreak.Core.Rendering.Materials;

namespace Daybreak.Core.Rendering.Pipeline
{
    /// <summary>
    /// Base class for objects used for various types of pipeline variables
    /// </summary>
    public abstract class PipelineAttribute
    {
        public SasSemantic Semantic;

        static PipelineAttribute()
        {
        }

        protected PipelineAttribute(SasSemantic sem)
        {
            Semantic = sem;
        }

        protected abstract void ApplyToParameter(EffectParameter param);

        public void SetParameterValue(EffectParameter param)
        {
            if (param == null)
                return;

            ApplyToParameter(param);
        }

    }

    public class BoolAttribute : PipelineAttribute
    {
        public bool Value;

        internal BoolAttribute(SasSemantic sem) : base(sem) { }

        protected override void ApplyToParameter(EffectParameter param)
        {
            param.SetValue(Value);
        }

    }

    public class FloatAttribute : PipelineAttribute
    {
        public float Value;

        internal FloatAttribute(SasSemantic sem) : base(sem) { }

        protected override void ApplyToParameter(EffectParameter param)
        {
            param.SetValue(Value);
        }

    }

    public class MatrixAttribute : PipelineAttribute
    {
        public Matrix Value;

        internal MatrixAttribute(SasSemantic sem) : base(sem) { }

        protected override void ApplyToParameter(EffectParameter param)
        {
            param.SetValue(Value);
        }

    }

    public class ColorAttribute : PipelineAttribute
    {
        public Color Value;

        public ColorAttribute(SasSemantic sem) : base(sem) { }

        protected override void ApplyToParameter(EffectParameter param)
        {
            if (param.ParameterType == EffectParameterType.Int32)
                param.SetValue(Value.PackedValue);
            else
            {
                if(param.ColumnCount == 4)
                    param.SetValue(Value.ToVector4());

                if (param.ColumnCount == 3)
                    param.SetValue(Value.ToVector3());
            }
        }

    }

    public class Vector3Attribute : PipelineAttribute
    {
        public Vector3 Value;

        public Vector3Attribute(SasSemantic sem) : base(sem) { }

        protected override void ApplyToParameter(EffectParameter param)
        {
            param.SetValue(Value);
        }

    }

    public class Texture2DAttribute : PipelineAttribute
    {
        public Texture2D Value;

        public Texture2DAttribute(SasSemantic sem) : base(sem) { }

        protected override void ApplyToParameter(EffectParameter param)
        {
            param.SetValue(Value);
        }

    }

    public class TextureCubeAttribute : PipelineAttribute
    {
        public TextureCube Value;

        public TextureCubeAttribute(SasSemantic sem) : base(sem) { }

        protected override void ApplyToParameter(EffectParameter param)
        {
            param.SetValue(Value);
        }

    }

    public class ObjectAttribute : PipelineAttribute, IObjectLifeTime
    {
        public ObjectAttribute(SasSemantic sem) : base(sem) { }

        protected override void ApplyToParameter(EffectParameter param)
        {
            throw new Exception("The method or operation is not implemented.");
        }
    }
}
